using System.Collections;
using UnityEngine;

namespace VoxelGame.NPC
{
	[RequireComponent(typeof(CharacterController))]
	public class Wander : NPCBehaviour
	{
		[SerializeField]
		private float _speed = 5f;

		[SerializeField]
		private float _angularSpeed = 2f;

		[SerializeField]
		private float _headingUpdateInterval = 2f;

		[SerializeField]
		private float _maxHeadingChange = 30f;

		[SerializeField]
		private float _avoidObstacleDistance = 5f;

		[SerializeField]
		private Vector2 _wanderArea;

		[SerializeField]
		private Vector3 _lineOfSight = new Vector3(0f, 0.5f, 0f);

		[SerializeField]
		private string _walkAnimation;

		private Quaternion _targetRotation;

		private bool _turnArround;

		private float _newHeadingUpdateTime;

		private void OnEnable()
		{
			PlayAnimation(_walkAnimation);
			float time = Random.Range(_minDuration, _maxDuration);
			StartCoroutine(WanderTime(time));
		}

		private IEnumerator WanderTime(float time)
		{
			yield return new WaitForSeconds(time);
			_npcControls.OnBehaviourFinished(this);
		}

		private void Update()
		{
			Move();
			AvoidObstacles();
			UpdateHeading();
		}

		private void OnDrawGizmos()
		{
			Vector3 size = new Vector3(_wanderArea.x * 2f, 50f, _wanderArea.y * 2f);
			Gizmos.color = Color.magenta;
			Gizmos.DrawWireCube(_npcControls.GetInitialPosition(), size);
		}

		private void UpdateHeading()
		{
			if (!IsInsideWanderArea())
			{
				_newHeadingUpdateTime = _headingUpdateInterval;
			}
			_newHeadingUpdateTime += Time.deltaTime;
			if (!(_newHeadingUpdateTime >= _headingUpdateInterval))
			{
				return;
			}
			if (IsInsideWanderArea())
			{
				if (!_turnArround)
				{
					RandomTargetRotation();
				}
			}
			else
			{
				RandomTargetPosition();
			}
		}

		private void Move()
		{
			base.transform.rotation = Quaternion.Slerp(base.transform.rotation, _targetRotation, Time.deltaTime * _angularSpeed);
			Vector3 a = base.transform.TransformDirection(Vector3.forward);
			_npcControls.SimpleMove(a * _speed);
		}

		private bool IsInsideWanderArea()
		{
			Vector3 initialPosition = _npcControls.GetInitialPosition();
			float x = initialPosition.x - _wanderArea.x;
			Vector3 initialPosition2 = _npcControls.GetInitialPosition();
			Vector2 vector = new Vector2(x, initialPosition2.z - _wanderArea.y);
			Vector3 initialPosition3 = _npcControls.GetInitialPosition();
			float x2 = initialPosition3.x + _wanderArea.x;
			Vector3 initialPosition4 = _npcControls.GetInitialPosition();
			Vector2 vector2 = new Vector2(x2, initialPosition4.z + _wanderArea.y);
			Vector3 position = base.transform.position;
			if (!(position.x >= vector2.x))
			{
				Vector3 position2 = base.transform.position;
				if (!(position2.x <= vector.x))
				{
					Vector3 position3 = base.transform.position;
					if (!(position3.z >= vector2.y))
					{
						Vector3 position4 = base.transform.position;
						if (!(position4.z <= vector.y))
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private void RandomTargetRotation()
		{
			Vector3 eulerAngles = base.transform.eulerAngles;
			float min = eulerAngles.y - _maxHeadingChange;
			Vector3 eulerAngles2 = base.transform.eulerAngles;
			float max = eulerAngles2.y + _maxHeadingChange;
			float angle = Random.Range(min, max);
			_targetRotation = Quaternion.AngleAxis(angle, Vector3.up);
		}

		private void RandomTargetPosition()
		{
			Vector3 forward = _npcControls.GetInitialPosition() - base.transform.position;
			_targetRotation = Quaternion.LookRotation(forward, Vector3.up);
			Vector3 eulerAngles = _targetRotation.eulerAngles;
			_targetRotation = Quaternion.AngleAxis(eulerAngles.y, Vector3.up);
		}

		private void AvoidObstacles()
		{
			float angleDirection = 0f;
			if (ForwardRayCast(out angleDirection, _npcControls.ColliderRadius()) || ForwardRayCast(out angleDirection, 0f - _npcControls.ColliderRadius()) || ForwardRayCast(out angleDirection, 0f))
			{
				TurnArround(angleDirection);
			}
			else
			{
				_turnArround = false;
			}
		}

		private void TurnArround(float angleDirection)
		{
			_turnArround = true;
			_targetRotation = Quaternion.AngleAxis(angleDirection, Vector3.up);
		}

		private bool ForwardRayCast(out float angleDirection, float xOffset)
		{
			Vector3 vector = _lineOfSight;
			vector.x += xOffset;
			vector = base.transform.TransformPoint(vector);
			if (_turnArround)
			{
				UnityEngine.Debug.DrawRay(vector, base.transform.forward * _avoidObstacleDistance, Color.red);
			}
			else
			{
				UnityEngine.Debug.DrawRay(vector, base.transform.forward * _avoidObstacleDistance, Color.blue);
			}
			RaycastHit hitInfo;
			bool flag = Physics.Raycast(vector, base.transform.forward, out hitInfo, _avoidObstacleDistance);
			if (flag)
			{
				Vector3 vector2 = hitInfo.normal * (_avoidObstacleDistance - hitInfo.distance) * 20f;
				angleDirection = vector2.x + vector2.z;
			}
			else
			{
				angleDirection = 0f;
			}
			return flag;
		}
	}
}
